import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ConfigService } from '@nestjs/config';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { JwtPayload, jwtPayloadToCurrentUser } from './types/jwt.type';
import { TokenBlacklistService } from '../common/services/token-blacklist.service';
import { RequestContextService } from '../common/services/request-context.service';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    configService: ConfigService,
    private readonly tokenBlacklistService: TokenBlacklistService,
    private readonly requestContext: RequestContextService
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: configService.get('JWT_SECRET') || '123456',
      passReqToCallback: true, // 传递 request 对象到 validate 方法
    });
  }

  async validate(request: any, payload: JwtPayload) {
    if (!payload.sub) {
      throw new UnauthorizedException('Invalid token');
    }

    // 从请求头提取 Token
    const token = ExtractJwt.fromAuthHeaderAsBearerToken()(request);

    // 检查 Token 是否在黑名单中
    if (token) {
      const isBlacklisted = await this.tokenBlacklistService.isBlacklisted(token);
      if (isBlacklisted) {
        throw new UnauthorizedException('Token 已失效，请重新登录');
      }
    }

    const user = jwtPayloadToCurrentUser(payload);

    // 直接设置到 CLS，确保 Guards 可以从 CLS 获取权限
    this.requestContext.setUser(user);

    return user;
  }
}

